/**   
*    
* @file
* @brief
*
* @<b>文件名</b>      : AudioRecordManager
* @n@n<b>版权所有</b>: 网龙应用软件开发一部
* @n@n<b>作  者</b>  : cb
* @n@n<b>创建时间</b>: 2014-2-28 下午4:44:36 
* @n@n<b>文件描述</b>:  
* @version  
*/
package com.common.android.utils.audio;

import java.io.File;

import com.common.android.utils.FormatUtils;

import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;

/**
 * ClassName:AudioRecordManager
 * Function: 录音管理费类(必须在主线程使用)
 * Reason:	 
 * @author   cb		
 * @version  Ver 1.3.3_modularization
 * @Date	 2014	2014-2-28		下午4:44:36
 *
 * @see 	 
 */

public class AudioRecordManager {
	public static final int STATE_RECORD=0;
	public static final int STATE_CANCEL=1;
	public class ERROR{
		public static final int TIME_TOO_SHORT=-1;	//录音时长太短
		public static final int STOP_EXCEPTION=-2;	//停止异常
		public static final int START_EXCEPTION=-3;	//开始异常
		public static final int UNKONW_EXCEPTION=-4;//未知异常
		public static final int EMPTY_FILE_NAME=-5;	//文件名为空·
		public static final int DELETE_FILE=-6;		//删除文件失败
		public static final int STILL_RECORDING=-7;	//正在录音当中
	}
	public interface onAudioRecordListener{
		//开始录音
		void onRecordStart();
		
		//录音成功 path:文件路径 time:录音的时长，单位是秒
		void onRecordSuccess(String path,long time);
		
		//录音失败 failType:失败的类型，见ERROR类 ;errMsg：失败的原因，有可能没有值
		void onRecordFail(int failType,String errMsg);
		
		//音量变化，time表示当前已录音多少秒
		void onVolumeChanged(int volume,long time);
	}
	private onAudioRecordListener mRecordListener;
	private static final int MIN_RECORD_DURATION=1000;	//最短的录音间隔时间。为了防止某些机型连续快速开启/停止录音造成界面卡死。
    private static final int STATE_SUCCESS=0;			//成功状态
    private static final int STATE_RECORDING=1;		//录音状态
    private static final int GET_VOLUME=2;			//获取音量
    private static final int DEFAULT_MAX_TIME=2*60*1000;	//默认的最大录音时间
    private static final int DEFAULT_MIN_TIME=1000;		//默认的最小录音时间
    
	private MediaRecorder mRecorder;
	private int mRecordState=-1;				//当前的录音状态
	private String mPath;						//录音文件存放的路径
	private MyThread mThread;					
	private long mStartTime;					//录音开始的时间
	private long mDuration=100L;				//获取音量的间隔
	private long mMaxRecordTime=DEFAULT_MAX_TIME;	//最大录音时长·
	private long mMinRecordTime=DEFAULT_MIN_TIME;	//最小录音时长
	private boolean mIsOperationProtect=false;
	public AudioRecordManager(onAudioRecordListener listener){
		mRecordListener=listener;
	}
	
	/**
	 * @n<b>函数名称</b>     :setVolumeChangeDuration
	 * @brief 设置获取音量的周期
	 * @version    Ver 1.3.3_modularization
	 * @param  @param duration
	 * @return void
	 * @<b>作者</b>          :  cb
	 * @<b>创建时间</b>      :  2014-2-28下午5:41:05      
	*/
	public void setVolumeChangeDuration(long duration){
		mDuration=duration;
	}
	
	/**
	 * @n<b>函数名称</b>     :setMaxRecordTime
	 * @brief 设置最大录音时长
	 * @version    Ver 1.3.3_modularization
	 * @param  @param time 时长，单位是秒
	 * @return void
	 * @<b>作者</b>          :  cb
	 * @<b>创建时间</b>      :  2014-2-28下午5:41:21      
	*/
	public void setMaxRecordTime(long time){
		mMaxRecordTime=time*1000;
	}
	
	/**
	 * @n<b>函数名称</b>     :setMinRecordTime
	 * @brief 设置最小录音时长
	 * @version    Ver 1.3.3_modularization
	 * @param  @param time
	 * @return void
	 * @<b>作者</b>          :  cb
	 * @<b>创建时间</b>      :  2014-2-28下午5:41:30      
	*/
	public void setMinRecordTime(long time){
		mMinRecordTime=time;
		if (time<=0){
			mMinRecordTime=2000L;
		}
	}
	
    /**
     * @n<b>函数名称</b>     :audioStart
     * @brief 开始录音
     * @version    Ver 1.3.3_modularization
     * @param  
     * @return void
     * @<b>作者</b>          :  cb
     * @<b>创建时间</b>      :  2014-2-28下午5:41:38      
    */
    @SuppressWarnings("deprecation")
	public boolean audioStart() {
    	if (mIsOperationProtect){
    		return false;
    	}
    	mIsOperationProtect=true;
    	//这个开始录音操作是用户启动的，在主线程里进行
		new Handler().postDelayed(new Runnable() {
			public void run() {
				mIsOperationProtect=false;
			}
		}, MIN_RECORD_DURATION);
        try {
        	if (mRecordState==STATE_RECORDING && mThread!=null && mThread.getState()!=Thread.State.TERMINATED){
        		//正在录音
        		Message message=mRecordHanler.obtainMessage();
            	message.what=ERROR.STILL_RECORDING;
            	mRecordHanler.sendMessage(message);
            	return false;
        	}
            // Log.d(TAG,"new MediaRecorder()");
        	if (TextUtils.isEmpty(mPath)){
            	Message message=mRecordHanler.obtainMessage();
            	message.what=ERROR.EMPTY_FILE_NAME;
            	mRecordHanler.sendMessage(message);
            	return false;
            }

//        	if (mRecorder==null){
        	if (mRecorder != null){
        	    mRecorder = null;
        	}
        		mRecorder = new MediaRecorder();
                mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
                mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);	
//        	}
            if (!new File(mPath).exists())
                new File(mPath).createNewFile();
            mRecorder.setOutputFile(mPath);
            if (mRecordState != STATE_RECORDING){
                mRecorder.prepare();
                mRecorder.start();
                mRecordState = STATE_RECORDING;
            }

            //下面代码会导致ANR，因为mThread.join()会导致死循环,BY JLH
//            if (mThread != null) {
//                try {
//                    mThread.join();
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//            }
            if (mThread == null || mThread.getState() != Thread.State.RUNNABLE) {
            	if (mRecordListener!=null){
            		mRecordListener.onRecordStart();
            	}
            	mStartTime=System.currentTimeMillis();
                mThread = new MyThread();
                mThread.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
            mRecordState = -1;
            Message message=mRecordHanler.obtainMessage();
        	message.what=ERROR.START_EXCEPTION;
        	message.obj=e.getMessage();
        	mRecordHanler.sendMessage(message);
            audioStop();
            return false;
        }
        return true;
    }

    /**
     * @n<b>函数名称</b>     :audioFinish
     * @brief 录音结束
     * @version    Ver 1.3.3_modularization
     * @param  
     * @return void
     * @<b>作者</b>          :  cb
     * @<b>创建时间</b>      :  2014-2-28下午5:41:49      
    */
    public void audioFinish() {
    	if (mRecordState==STATE_RECORDING){
    		//如果正在录音,先停止,获取录音成功与否的状态
    		mRecordState=audioStop();
    	}
        if (mRecordState==STATE_SUCCESS) {
        	//录音成功
        	Message message=mRecordHanler.obtainMessage();
        	message.obj=System.currentTimeMillis()-mStartTime;
        	message.what=mRecordState;
        	mRecordHanler.sendMessage(message);
        } 
    }

    /**
     * @n<b>函数名称</b>     :audioStop
     * @brief 录音中断
     * @version    Ver 1.3.3_modularization
     * @param  @return
     * @return int
     * @<b>作者</b>          :  cb
     * @<b>创建时间</b>      :  2014-2-28下午5:41:56      
    */
    public int audioStop() {
        try {
            if (mRecorder != null && mRecordState != -1) {
                mRecorder.stop();
                mRecorder.reset();
                mRecorder.release();
                mRecorder = null;
            }
        } catch (IllegalStateException e) {
            // 在某种情况下调用stop()方法会遇到IllegalStateException
            mRecordState = -1;
        	Message message=mRecordHanler.obtainMessage();
        	message.what=ERROR.STOP_EXCEPTION;
        	message.obj=e.getMessage();
        	mRecordHanler.sendMessage(message);
        	return ERROR.STOP_EXCEPTION;

        } catch (RuntimeException e){
            mRecordState = -1;
        	Message message=mRecordHanler.obtainMessage();
        	message.what=ERROR.STOP_EXCEPTION;
        	message.obj=e.getMessage();
        	mRecordHanler.sendMessage(message);
            return ERROR.STOP_EXCEPTION;
        }
        if (mThread != null && mThread.isAlive() && mThread.getState() == Thread.State.RUNNABLE) {
        	mThread.interrupt();
        	mThread=null;
//            try {
//                mThread.join();
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
        }
        if (System.currentTimeMillis() - mStartTime < mMinRecordTime) {
        	//录音时间太短
        	Message message=mRecordHanler.obtainMessage();
        	message.what=ERROR.TIME_TOO_SHORT;
        	mRecordHanler.sendMessage(message);
        	return ERROR.TIME_TOO_SHORT;
        }
        return STATE_SUCCESS;
    }
    
    class MyThread extends Thread {
        @Override
        public void run() {
            super.run();
            while (mRecordState==STATE_RECORDING) {
            	//在录音状态下，每隔固定的时间获取一次音量
                if (mRecorder != null) {
                	int value = 0;
                	try {
                		value = mRecorder.getMaxAmplitude();
					} catch (Exception e) {
						//有可能获取音量会出异常
						value = 0;
					}
                	Message message=mRecordHanler.obtainMessage();
                  	message.what=GET_VOLUME;
                  	message.arg1=value;
                    mRecordHanler.sendMessage(message);

                    if (System.currentTimeMillis()-mStartTime>=mMaxRecordTime){
                    	audioFinish();
                    }
                    try {
                        Thread.sleep(mDuration);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    };
    
    private Handler mRecordHanler=new Handler(){
    	public void handleMessage(android.os.Message msg) {
    		super.handleMessage(msg);
    		if (mRecordListener==null){
    			return;
    		}
    		switch (msg.what) {
			case GET_VOLUME:
				int volume=msg.arg1;
				long nowtime=System.currentTimeMillis()-mStartTime;
				mRecordListener.onVolumeChanged(volume,FormatUtils.millsec2Sec(nowtime));
				break;
			case STATE_SUCCESS:
				try {
					long time=(Long)msg.obj;
					mRecordListener.onRecordSuccess(mPath, time);
				} catch (Exception e) {
				}
				break;
			default:
				int type=msg.what;
                mRecordState = -1;
				mRecordListener.onRecordFail(type, (String) msg.obj);
				deleteRecordFile();
				break;
			}
    	};
    };
    
    /**
     * @n<b>函数名称</b>     :deleteRecordFile
     * @brief 删除录音文件（在出错的时候进行）
     * @version    Ver 1.3.3_modularization
     * @param  
     * @return void
     * @<b>作者</b>          :  cb
     * @<b>创建时间</b>      :  2014-2-28下午5:42:33      
    */
    private void deleteRecordFile(){
    	try {
    		File file=new File(mPath);
    		if (file.exists()){
    			file.delete();	
    		}
		} catch (Exception e) {
			if (mRecordListener!=null){
				mRecordListener.onRecordFail(ERROR.DELETE_FILE, e.getMessage());
			}
		}
    }
    
	/**
	 * 动态设置录音文件路径
	 * 
	 * @n<b>函数名称</b> :setRecrodPath
	 * @brief
	 * @see
	 * @version Ver 1.3.x
	 * @param @param path
	 * @return void
	 * @<b>作者</b> : HuangYK
	 * @<b>创建时间</b> : 2014-3-18下午4:11:40
	 */
	public void setRecrodPath(String path) {
		mPath = path;
	}
}
